﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Operations;

namespace Expect.Vs2010.Extensions.Intellisense
{
    using System.Linq;

    using Expect.VisualStudio.Extensions;

    using Microsoft.VisualStudio.Shell;

    internal class ExpectCompletionSource : ICompletionSource
    {
        private ExpectCompletionSourceProvider m_sourceProvider;
        private ITextBuffer _buffer;
        private List<Completion> completions;
        private IExpectVSService _expectService;

        public ExpectCompletionSource(ExpectCompletionSourceProvider sourceProvider, ITextBuffer textBuffer)
        {
            m_sourceProvider = sourceProvider;
            _buffer = textBuffer;
            _expectService = (IExpectVSService)Package.GetGlobalService(typeof(SExpectVSService));
            
        }

        void ICompletionSource.AugmentCompletionSession(ICompletionSession session, IList<CompletionSet> completionSets)
        {
            ITextSnapshot snapshot = _buffer.CurrentSnapshot;
            var triggerPoint = (SnapshotPoint)session.GetTriggerPoint(snapshot);

            if (triggerPoint == null)
                return;

            var line = triggerPoint.GetContainingLine();
            
            var span = line.Extent.Span;
            //var str = line.Extent.GetText();

            var declarations = _expectService.GetIntellisenseDeclarations();
            completions = new List<Completion>();
            foreach (var declaration in declarations)
            {
                completions.Add(new Completion(declaration.DisplayText, declaration.InsertionText, declaration.Description, null, null));
            }

            var applicableTo = snapshot.CreateTrackingSpan(span, SpanTrackingMode.EdgeInclusive);
            if (completions.Count > 0)
            {
                completionSets.Add(new CompletionSet("All", "All", applicableTo, completions, Enumerable.Empty<Completion>()));
            }
            else
            {
                session.Dismiss();
            }
        }

        private ITrackingSpan FindTokenSpanAtPosition(ITrackingPoint point, ICompletionSession session)
        {
            SnapshotPoint currentPoint = (session.TextView.Caret.Position.BufferPosition);
            ITextStructureNavigator navigator = m_sourceProvider.NavigatorService.GetTextStructureNavigator(_buffer);
            TextExtent extent = navigator.GetExtentOfWord(currentPoint);
            var res = currentPoint.Snapshot.CreateTrackingSpan(extent.Span, SpanTrackingMode.EdgeInclusive);
            return res;
        }

        private bool m_isDisposed;

        public void Dispose()
        {
            if (!m_isDisposed)
            {
                GC.SuppressFinalize(this);
                m_isDisposed = true;
            }
        }
    }
}
